package com.sooth.micro.business.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.dream.antlr.smt.AliasStatement;
import com.dream.antlr.smt.ListColumnStatement;
import com.dream.antlr.smt.SymbolStatement;
import com.dream.antlr.sql.*;
import com.dream.drive.config.DriveProperties;
import com.dream.drive.factory.DefaultDriveFactory;
import com.dream.drive.factory.DriveFactory;
import com.dream.drive.listener.DebugListener;
import com.dream.drive.transaction.TransManager;
import com.dream.flex.def.*;
import com.dream.system.config.Configuration;
import com.sooth.common.core.exception.ServiceException;
import com.sooth.common.core.lang.SnowFlake;
import com.sooth.micro.app.service.IMicroAppService;
import com.sooth.micro.app.view.MicroAppBo;
import com.sooth.micro.business.view.*;
import com.sooth.micro.entity.service.IMicroEntityService;
import com.sooth.micro.entity.view.MicroEntityVo;
import com.sooth.micro.field.service.IMicroFieldService;
import com.sooth.micro.field.view.MicroFieldBo;
import com.sooth.micro.model.view.MicroModelBo;
import com.sooth.system.datasource.event.DatasourceEvent;
import com.sooth.system.datasource.service.ISysDatasourceService;
import com.sooth.system.datasource.view.SysDataSourceBo;
import com.zaxxer.hikari.HikariDataSource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.sql.DataSource;
import java.io.Closeable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import static com.dream.flex.def.FunctionDef.*;

@Slf4j
@RequiredArgsConstructor
@Service
public class MicroBusinessServiceImpl implements IMicroBusinessService {
    private final IMicroAppService microAppService;
    private final ISysDatasourceService datasourceService;
    private final IMicroEntityService entityService;
    private final IMicroFieldService fieldService;
    private Map<Long, DriveFactory> driveFactoryMap = new ConcurrentHashMap<>();
    private SnowFlake snowFlake = new SnowFlake();

    @EventListener
    public void refreshDbAll(DatasourceEvent datasourceEvent) {
        if (CollUtil.isNotEmpty(driveFactoryMap)) {
            DriveFactory driveFactory = driveFactoryMap.remove(datasourceEvent.getDatasourceId());
            if (driveFactory != null) {
                Configuration configuration = driveFactory.session().getConfiguration();
                DataSource dataSource = configuration.getDataSourceFactory().getDataSource();
                if (dataSource instanceof Closeable) {
                    try {
                        ((Closeable) dataSource).close();
                    } catch (Exception e) {
                        log.error("数据源关闭失败，原因：" + e.getMessage());
                    }
                }
            }
        }
    }

    /**
     * 根据字段获取表关联信息
     *
     * @param entityVo
     * @param columns
     * @return
     */
    private TableDef getTableDef(MicroEntityVo entityVo, List<QueryColumnVo> columns) {
        String tableName = entityVo.getTableName();
        Set<String> tableSet = new HashSet<>();
        tableSet.add(tableName);
        TableDef tableDef = table(tableName);
        for (QueryColumnVo queryColumnVo : columns) {
            String joinTableName = queryColumnVo.getTableName();
            if (!tableSet.contains(joinTableName)) {
                MicroModelBo model = queryColumnVo.getModel();
                TableDef.JoinOnDef joinOnDef;
                if (model.getLeftJoin().equals(1)) {
                    joinOnDef = tableDef.leftJoin(table(joinTableName));
                } else {
                    joinOnDef = tableDef.innerJoin(table(joinTableName));
                }
                ListColumnStatement tableStatement = new ListColumnStatement(".");
                tableStatement.add(column(tableName).getStatement());
                tableStatement.add(column(model.getEntityField()).getStatement());
                ListColumnStatement joinTableStatement = new ListColumnStatement(".");
                joinTableStatement.add(column(queryColumnVo.getTableName()).getStatement());
                joinTableStatement.add(column(model.getJoinEntityField()).getStatement());
                ColumnDef tableColumnDef = new ColumnDef(tableStatement);
                ColumnDef joinTableColumnDef = new ColumnDef(joinTableStatement);
                tableDef = joinOnDef.on(tableColumnDef.eq(joinTableColumnDef));
                tableSet.add(joinTableName);
            }
        }
        return tableDef;
    }

    private ColumnDef[] getVoColumnDefs(List<QueryColumnVo> columns) {
        ColumnDef[] columnDefs = new ColumnDef[columns.size()];
        for (int i = 0; i < columns.size(); i++) {
            QueryColumnVo queryColumnVo = columns.get(i);
            String tableName = queryColumnVo.getTableName();
            String column = queryColumnVo.getColumn();
            ListColumnStatement columnStatement = new ListColumnStatement(".");
            columnStatement.add(column(tableName).getStatement());
            columnStatement.add(column(column).getStatement());
            AliasStatement aliasStatement = new AliasStatement();
            aliasStatement.setColumn(columnStatement);
            if (StrUtil.isNotEmpty(queryColumnVo.getId())) {
                aliasStatement.setAlias(new SymbolStatement.SingleMarkStatement(queryColumnVo.getId()));
            }
            columnDefs[i] = new ColumnDef(aliasStatement);
        }
        return columnDefs;
    }

    private ColumnDef[] getBoColumnDefs(List<QueryColumnBo> columns) {
        ColumnDef[] columnDefs = new ColumnDef[columns.size()];
        for (int i = 0; i < columns.size(); i++) {
            QueryColumnBo queryColumn = columns.get(i);
            String column = queryColumn.getColumn();
            String alias = queryColumn.getAlias();
            if (StrUtil.isEmpty(alias)) {
                columnDefs[i] = column(column);
            } else {
                columnDefs[i] = column(column).as(alias);
            }
        }
        return columnDefs;
    }

    private QueryDef getQueryDef(WhereDef whereDef, List<QueryParam> params) {
        QueryDef queryDef = whereDef;
        if (CollUtil.isNotEmpty(params)) {
            ConditionDef conditionDef = null;
            for (QueryParam queryParam : params) {
                Object value = queryParam.getValue();
                String column = queryParam.getColumn();
                String condition = queryParam.getCondition();
                String label = queryParam.getLabel();
                if (StrUtil.isEmpty(column)) {
                    throw new ServiceException("查询字段`" + label + "`请先绑定数据字段");
                }
                if (StrUtil.isEmpty(condition)) {
                    throw new ServiceException("查询字段`" + label + "`请先绑定查询条件");
                }
                ConditionDef _conditionDef = null;
                switch (condition) {
                    case "eq":
                        _conditionDef = column(column).eq(value);
                        break;
                    case "like":
                        _conditionDef = column(column).like(value);
                        break;
                    case "like_left":
                        _conditionDef = column(column).likeLeft(value);
                        break;
                    case "like_right":
                        _conditionDef = column(column).likeRight(value);
                        break;
                    case "between":
                        if (value != null) {
                            if (value instanceof Object[]) {
                                Object[] val = (Object[]) value;
                                if (val.length == 2) {
                                    _conditionDef = column(column).between(val[0], val[1]);
                                }
                            } else if (value instanceof List) {
                                List val = (List) value;
                                if (val.size() == 2) {
                                    _conditionDef = column(column).between(val.get(0), val.get(1));
                                }
                            } else {
                                throw new ServiceException("查询条件为`范围区间`，参数类型必须是数组");
                            }
                        }
                        break;
                    case "in":
                        if (value != null) {
                            if (value instanceof Object[]) {
                                Object[] val = (Object[]) value;
                                if (val.length > 0) {
                                    _conditionDef = column(column).in(val);
                                }
                            } else if (value instanceof List) {
                                List val = (List) value;
                                if (!val.isEmpty()) {
                                    _conditionDef = column(column).in(val.toArray());
                                }
                            } else {
                                throw new ServiceException("查询条件为`范围包含`，参数类型必须是数组");
                            }
                        }
                        break;
                    default:
                        throw new ServiceException("查询条件`" + condition + "`不支持");
                }
                if (_conditionDef != null) {
                    if (conditionDef == null) {
                        conditionDef = _conditionDef;
                    } else {
                        conditionDef = conditionDef.and(_conditionDef);
                    }
                }
            }
            if (conditionDef != null) {
                queryDef = whereDef.where(conditionDef);
            }
        }
        return queryDef;
    }

    private MicroAppBo microApp(Long appId) {
        MicroAppBo microApp = microAppService.selectById(appId);
        if (microApp == null) {
            throw new ServiceException("应用不能空");
        }
        return microApp;
    }

    private MicroFieldBo selectPkByEntityId(Long entityId) {
        List<MicroFieldBo> pkFieldList = fieldService.selectPkByEntityId(entityId);
        if (CollUtil.isEmpty(pkFieldList) || pkFieldList.size() > 1) {
            throw new ServiceException("业务实体必须存在主键，且主键数量为1");
        }
        return pkFieldList.get(0);
    }

    private MicroEntityVo selectVoEntityId(Long entityId) {
        MicroEntityVo entityVo = entityService.selectVoById(entityId);
        if (entityVo == null) {
            throw new ServiceException("业务实体不能为空");
        }
        return entityVo;
    }

    @Override
    public Object list(QueryVo queryVo) {
        MicroAppBo microApp = microApp(queryVo.getAppId());
        List<QueryColumnVo> columns = queryVo.getColumns();
        if (columns == null) {
            columns = new ArrayList<>();
        }
        MicroFieldBo pkField = selectPkByEntityId(microApp.getEntityId());
        List<MicroModelBo> modelList = microApp.getModelList();
        QueryColumnVo pkQueryColumnVo = new QueryColumnVo();
        pkQueryColumnVo.setEntityId(microApp.getEntityId());
        pkQueryColumnVo.setColumn(pkField.getFieldCode());
        columns.add(pkQueryColumnVo);
        Map<Long, MicroEntityVo> entityMap = new HashMap<>();
        for (QueryColumnVo queryColumnVo : columns) {
            Long entityId = queryColumnVo.getEntityId();
            MicroEntityVo microEntity = entityMap.get(entityId);
            if (microEntity == null) {
                microEntity = entityService.selectVoById(entityId);
                if (microEntity == null) {
                    throw new ServiceException("字段：" + queryColumnVo.getColumn() + "所属实体不存在");
                }
                entityMap.put(entityId, microEntity);
            }
            if (!microApp.getEntityId().equals(entityId)) {
                for (MicroModelBo model : modelList) {
                    if (model.getJoinEntityId().equals(entityId)) {
                        queryColumnVo.setModel(model);
                    }
                }
                if (queryColumnVo.getModel() == null) {
                    throw new ServiceException("查询字段：" + queryColumnVo.getColumn() + "所属关联实体与业务实体不存在关联关系");
                }
            }
            queryColumnVo.setTableName(microEntity.getTableName());
        }
        MicroEntityVo entityVo = entityMap.get(microApp.getEntityId());
        Long datasourceId = entityVo.getDatasourceId();
        DriveFactory driveFactory = driveFactory(datasourceId);
        WhereDef whereDef = select(getVoColumnDefs(queryVo.getColumns())).from(getTableDef(entityVo, columns));
        QueryDef queryDef = getQueryDef(whereDef, queryVo.getParams());
        if (queryVo.isPagination()) {
            return driveFactory.flexMapper().selectPage(queryDef, Map.class, queryVo.getPage());
        } else {
            return driveFactory.flexMapper().selectList(queryDef, Map.class);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int remove(RemoveBo removeBo) {
        MicroAppBo microApp = microApp(removeBo.getAppId());
        MicroFieldBo pkField = selectPkByEntityId(microApp.getEntityId());
        String primColumn = pkField.getFieldCode();
        Object primValue = removeBo.getValue();
        MicroEntityVo entityVo = entityService.selectVoById(microApp.getEntityId());
        List<MicroModelBo> modelList = microApp.getModelList();
        DriveFactory driveFactory = driveFactory(entityVo.getDatasourceId());
        if (CollUtil.isNotEmpty(modelList)) {
            SaveResult saveResult = new SaveResult();
            saveResult.setPrimColumn(primColumn);
            saveResult.setPrimVlue(primValue);
            removeSubForm(entityVo, microApp.getModelList(), saveResult);
        }
        DeleteDef deleteDef = delete(table(entityVo.getTableName())).where(column(primColumn).eq(primValue));
        return driveFactory.flexMapper().delete(deleteDef);
    }

    /**
     * 删除子表单
     *
     * @param entityVo
     * @param modelList
     */
    private void removeSubForm(MicroEntityVo entityVo, List<MicroModelBo> modelList, SaveResult saveResult) {
        DriveFactory driveFactory = driveFactory(entityVo.getDatasourceId());
        List<String> columns = new ArrayList<>(modelList.size());
        for (MicroModelBo model : modelList) {
            if (!columns.contains(model.getEntityField())) {
                columns.add(model.getEntityField());
            }
        }
        ColumnDef[] columnDefs = new ColumnDef[columns.size()];
        for (int i = 0; i < columns.size(); i++) {
            columnDefs[i] = column(columns.get(i));
        }
        QueryDef queryDef = select(columnDefs).from(table(entityVo.getTableName())).where(column(saveResult.getPrimColumn()).eq(saveResult.getPrimVlue()));
        Map<String, Object> masterMap = driveFactory.flexMapper().selectOne(queryDef, Map.class);
        if (masterMap != null) {
            for (MicroModelBo model : modelList) {
                String entityField = model.getEntityField();
                Object value = masterMap.get(entityField);
                if (ObjectUtil.isNotEmpty(value)) {
                    Long joinEntityId = model.getJoinEntityId();
                    MicroEntityVo microEntityVo = entityService.selectVoById(joinEntityId);
                    if (microEntityVo != null) {
                        DeleteDef deleteDef = delete(table(microEntityVo.getTableName())).where(column(model.getJoinEntityField()).eq(value));
                        driveFactory.flexMapper().delete(deleteDef);
                    }
                }
            }
        }
    }

    private void querySubForm(Map<String, Object> resultMap, DriveFactory driveFactory, List<QuerySubFormBo> subForms) {
        for (QuerySubFormBo subForm : subForms) {
            MicroEntityVo entityVo = selectVoEntityId(subForm.getEntityId());
            MicroFieldBo pkField = selectPkByEntityId(subForm.getEntityId());
            List<QueryColumnBo> columns = subForm.getColumns();
            if (columns == null) {
                columns = new ArrayList<>();
            }
            QueryColumnBo pkQueryColumnBo = new QueryColumnBo();
            pkQueryColumnBo.setColumn(pkField.getFieldCode());
            columns.add(0, pkQueryColumnBo);
            ColumnDef[] columnDefs = getBoColumnDefs(columns);
            QueryDef queryDef = select(columnDefs).from(table(entityVo.getTableName())).where(column(subForm.getModel().getJoinEntityField()).eq(resultMap.get(subForm.getModel().getEntityField())));
            Object subFormResult;
            if (subForm.isMul()) {
                subFormResult = driveFactory.flexMapper().selectList(queryDef, Map.class);
            } else {
                subFormResult = driveFactory.flexMapper().selectOne(queryDef, Map.class);
            }
            resultMap.put("$" + subForm.getEntityId(), subFormResult);
        }
    }

    @Override
    public Object query(QueryBo queryBo) {
        MicroAppBo microApp = microApp(queryBo.getAppId());
        MicroFieldBo pkField = selectPkByEntityId(microApp.getEntityId());
        List<QueryColumnBo> columns = queryBo.getColumns();
        String primaryColumn = pkField.getFieldCode();
        if (columns == null) {
            columns = new ArrayList<>();
        }
        QueryColumnBo pkQueryColumn = new QueryColumnBo();
        pkQueryColumn.setColumn(primaryColumn);
        columns.add(0, pkQueryColumn);
        List<MicroModelBo> modelList = microApp.getModelList();
        if (CollUtil.isNotEmpty(modelList)) {
            List<String> fieldList = modelList.stream().map(model -> model.getEntityField()).distinct().collect(Collectors.toList());
            for (String field : fieldList) {
                if (!field.equals(pkQueryColumn)) {
                    QueryColumnBo queryColumnBo = new QueryColumnBo();
                    queryColumnBo.setColumn(field);
                    columns.add(queryColumnBo);
                }
            }
        }
        Long entityId = microApp.getEntityId();
        MicroEntityVo entityVo = selectVoEntityId(entityId);
        DriveFactory driveFactory = driveFactory(entityVo.getDatasourceId());
        ColumnDef[] columnDefs = getBoColumnDefs(columns);
        QueryDef queryDef = select(columnDefs).from(table(entityVo.getTableName())).where(column(primaryColumn).eq(queryBo.getValue()));
        Map resultMap = driveFactory.flexMapper().selectOne(queryDef, Map.class);
        if (resultMap != null) {
            List<QuerySubFormBo> subForms = queryBo.getSubForms();
            if (CollUtil.isNotEmpty(subForms)) {
                for (QuerySubFormBo subForm : subForms) {
                    for (MicroModelBo model : modelList) {
                        if (subForm.getEntityId().equals(model.getJoinEntityId())) {
                            subForm.setModel(model);
                            break;
                        }
                        if (subForm.getModel() == null) {
                            throw new ServiceException("实体关系模型配置错误");
                        }
                    }
                }
                querySubForm(resultMap, driveFactory, subForms);
            }
        }
        return resultMap;
    }

    private Object primValue(String primaryType) {
        Long nextValue = snowFlake.next();
        Object primaryValue;
        switch (primaryType) {
            case "input" -> primaryValue = String.valueOf(nextValue);
            case "number" -> primaryValue = nextValue;
            default -> throw new ServiceException("主键类型必须是数字或者字符");
        }
        return primaryValue;
    }

    private void mergeAddValue(List<SaveColumnBo> columns, List<MicroFieldBo> fieldList) {
        Map<String, Object> map = new HashMap<>(columns.size() + fieldList.size());
        for (SaveColumnBo column : columns) {
            map.put(column.getColumn(), column.getValue());
        }
        for (MicroFieldBo field : fieldList) {
            Object value = map.get(field.getFieldCode());
            if (ObjectUtil.isEmpty(value)) {
                map.put(field.getFieldCode(), field.getAddValue());
            }
        }
    }

    private void mergeEditValue(List<SaveColumnBo> columns, List<MicroFieldBo> fieldList) {
        Map<String, Object> map = new HashMap<>(columns.size() + fieldList.size());
        for (SaveColumnBo column : columns) {
            map.put(column.getColumn(), column.getValue());
        }
        for (MicroFieldBo field : fieldList) {
            Object value = map.get(field.getFieldCode());
            if (ObjectUtil.isEmpty(value)) {
                map.put(field.getFieldCode(), field.getEditValue());
            }
        }
    }

    private InsertDef insertDef(MicroEntityVo microEntity, List<SaveColumnBo> columns) {
        int len = columns.size() + 1;
        List<ColumnDef> columnDefs = new ArrayList<>(len);
        List<Object> values = new ArrayList<>(len);
        for (int i = 0; i < columns.size(); i++) {
            SaveColumnBo saveColumn = columns.get(i);
            String column = saveColumn.getColumn();
            columnDefs.add(column(column));
            values.add(saveColumn.getValue());
        }
        InsertDef insertDef = insertInto(table(microEntity.getTableName())).columns(columnDefs.toArray(new ColumnDef[0])).values(values.toArray());
        return insertDef;
    }

    private UpdateDef updateDef(MicroEntityVo microEntity, List<SaveColumnBo> columns, SaveResult saveResult) {
        UpdateColumnDef updateColumnDef = update(table(microEntity.getTableName()));
        for (SaveColumnBo saveColumn : columns) {
            updateColumnDef.set(column(saveColumn.getColumn()), saveColumn.getValue());
        }
        UpdateDef updateDef = updateColumnDef.where(column(saveResult.getPrimColumn()).eq(saveResult.getPrimVlue()));
        return updateDef;
    }

    private InsertDef insertDef(MicroModelBo tableModel, MicroEntityVo entityVo, List<SaveColumnBo> columns, Object joinValue) {
        MicroFieldBo pkField = selectPkByEntityId(entityVo.getId());
        String primaryColumn = pkField.getFieldCode();
        boolean hasPrim = false;
        boolean hasJoinColumn = false;
        for (SaveColumnBo microColumn : columns) {
            if (StrUtil.isNotEmpty(primaryColumn) && primaryColumn.equals(microColumn.getColumn())) {
                hasPrim = true;
                if (microColumn.getValue() == null) {
                    Object primValue = primValue(pkField.getFieldType());
                    microColumn.setValue(primValue);
                }
            }
            if (tableModel.getJoinEntityField().equals(microColumn.getColumn())) {
                hasJoinColumn = true;
                microColumn.setValue(joinValue);
            }
        }
        if (!hasJoinColumn) {
            SaveColumnBo microColumn = new SaveColumnBo();
            microColumn.setColumn(tableModel.getJoinEntityField());
            microColumn.setValue(joinValue);
            columns.add(0, microColumn);
        }
        if (!hasPrim && StrUtil.isNotEmpty(primaryColumn)) {
            SaveColumnBo saveColumnBo = new SaveColumnBo();
            saveColumnBo.setColumn(primaryColumn);
            saveColumnBo.setValue(primValue(pkField.getFieldType()));
            columns.add(0, saveColumnBo);
        }
        ColumnDef[] columnDefs = new ColumnDef[columns.size()];
        Object[] values = new Object[columns.size()];
        for (int i = 0; i < columns.size(); i++) {
            SaveColumnBo microColumn = columns.get(i);
            columnDefs[i] = column(microColumn.getColumn());
            values[i] = microColumn.getValue();
        }
        InsertDef insertDef = insertInto(table(entityVo.getTableName())).columns(columnDefs).values(values);
        return insertDef;
    }

    private void saveSubForm(DriveFactory driveFactory, Map<String, Object> masterMap, List<SaveSubFormBo> subForms) {
        for (SaveSubFormBo subFormBo : subForms) {
            Long joinEntityId = subFormBo.getEntityId();
            String column = subFormBo.getModel().getEntityField();
            String joinColumn = subFormBo.getModel().getJoinEntityField();
            Object value = masterMap.get(column);
            if (value == null) {
                throw new ServiceException("属性字段" + column + "值不能为空");
            }
            MicroEntityVo joinEntity = selectVoEntityId(joinEntityId);
            String tableName = joinEntity.getTableName();
            List<SaveColumnBo> sinColumns = subFormBo.getSinColumns();
            List<List<SaveColumnBo>> mulColumns = subFormBo.getMulColumns();
            DeleteDef deleteDef = delete(table(tableName)).where(column(joinColumn).eq(value));
            driveFactory.flexMapper().delete(deleteDef);
            if (CollUtil.isNotEmpty(sinColumns)) {
                InsertDef insertDef = insertDef(subFormBo.getModel(), joinEntity, sinColumns, value);
                driveFactory.flexMapper().insert(insertDef);
            } else if (CollUtil.isNotEmpty(mulColumns)) {
                for (List<SaveColumnBo> mulColumn : mulColumns) {
                    InsertDef insertDef = insertDef(subFormBo.getModel(), joinEntity, mulColumn, value);
                    driveFactory.flexMapper().insert(insertDef);
                }
            }

        }
    }

    @Override
    public SaveResult save(SaveBo saveBo) {
        MicroAppBo microApp = microApp(saveBo.getAppId());
        MicroFieldBo pkField = selectPkByEntityId(microApp.getEntityId());
        MicroEntityVo entityVo = selectVoEntityId(microApp.getEntityId());
        DriveFactory driveFactory = driveFactory(entityVo.getDatasourceId());
        SaveResult saveResult = new SaveResult();
        saveResult.setPrimColumn(pkField.getFieldCode());
        saveResult.setPrimType(pkField.getFieldType());
        List<SaveSubFormBo> subForms = saveBo.getSubForms();
        if (CollUtil.isNotEmpty(subForms)) {
            for (SaveSubFormBo subForm : subForms) {
                for (MicroModelBo model : microApp.getModelList()) {
                    if (subForm.getEntityId().equals(model.getJoinEntityId())) {
                        subForm.setModel(model);
                        break;
                    }
                    if (subForm.getModel() == null) {
                        throw new ServiceException("实体关系模型配置错误");
                    }
                }
            }
        }
        TransManager.exec(() -> {
            List<SaveColumnBo> columns = saveBo.getColumns();
            Object primValue = saveBo.getPrimaryValue();
            if (primValue == null) {
                List<MicroFieldBo> fieldList = fieldService.selectAddValueByEntityId(entityVo.getId());
                mergeAddValue(columns, fieldList);
                for (SaveColumnBo column : columns) {
                    if (column.getColumn().equals(pkField.getFieldCode())) {
                        primValue = column.getValue();
                        break;
                    }
                }
                if (primValue == null) {
                    primValue = primValue(pkField.getFieldType());
                    SaveColumnBo pkSaveColumnBo = new SaveColumnBo();
                    pkSaveColumnBo.setColumn(pkField.getFieldCode());
                    pkSaveColumnBo.setValue(primValue);
                    columns.add(0, pkSaveColumnBo);
                }
                saveResult.setPrimVlue(primValue);
                InsertDef insertDef = insertDef(entityVo, columns);
                driveFactory.flexMapper().insert(insertDef);
            } else {
                saveResult.setPrimVlue(primValue);
                List<MicroFieldBo> fieldList = fieldService.selectEditValueByEntityId(entityVo.getId());
                mergeEditValue(columns, fieldList);
                UpdateDef updateDef = updateDef(entityVo, columns, saveResult);
                driveFactory.flexMapper().update(updateDef);
            }
            if (CollUtil.isNotEmpty(subForms)) {
                Map<String, Object> masterMap = new HashMap<>();
                for (SaveColumnBo column : columns) {
                    masterMap.put(column.getColumn(), column.getValue());
                }
                saveSubForm(driveFactory, masterMap, subForms);
            }
            return true;
        });
        return saveResult;
    }

    private DriveFactory driveFactory(Long datasourceId) {
        DriveFactory driveFactory = driveFactoryMap.get(datasourceId);
        if (driveFactory == null) {
            SysDataSourceBo dataSourceBo = datasourceService.selectById(datasourceId);
            if (dataSourceBo == null) {
                throw new ServiceException("数据源id：" + datasourceId + "不存在");
            }
            String url = dataSourceBo.getUrl();
            Class<? extends ToSQL> toSQLType = parseDbType(url);
            HikariDataSource dataSource = new HikariDataSource();
            dataSource.setJdbcUrl(url);
            dataSource.setUsername(dataSourceBo.getUsername());
            dataSource.setPassword(dataSourceBo.getPassword());
            DriveProperties driveProperties = new DriveProperties();
            driveProperties.setToSQL(toSQLType.getName());
            driveProperties.setListeners(new String[]{DebugListener.class.getName()});
            driveFactory = new DefaultDriveFactory(dataSource, null, null, driveProperties);
            driveFactoryMap.put(datasourceId, driveFactory);
        }
        return driveFactory;
    }

    private Class<? extends ToSQL> parseDbType(String jdbcUrl) {
        jdbcUrl = jdbcUrl.toLowerCase();
        if (jdbcUrl.contains(":mysql:") || jdbcUrl.contains(":cobar:") || jdbcUrl.contains(":mariadb:")) {
            return ToMYSQL.class;
        } else if (jdbcUrl.contains(":oracle:")) {
            return ToORACLE.class;
        } else if (jdbcUrl.contains(":sqlserver2012:") || jdbcUrl.contains(":sqlserver:") || jdbcUrl.contains(":microsoft:")) {
            return ToMSSQL.class;
        } else if (jdbcUrl.contains(":postgresql:")) {
            return ToPGSQL.class;
        } else if (jdbcUrl.contains(":dm")) {
            return ToDM.class;
        }
        return ToMYSQL.class;
    }
}
